package AICore;

import game.Player;

import java.util.LinkedList;

import AICore.WinningPattern.PatternAction;

import carddeck.Card;
import carddeck.Rank;
import carddeck.Suit;

public class WinningPatternsFactory {
	public static LinkedList<WinningPattern> create(LinkedList<Card> cards, int movesToWin) {
		if(movesToWin==2)
			return createOfTwo(cards);
		else if(movesToWin==3)
			return createOfThree(cards);
		else
			return null;
	}
	
	public static LinkedList<WinningPattern> createOfTwo(LinkedList<Card> cards) {
		LinkedList<WinningPattern> patterns = new LinkedList<>();
		LinkedList<Card> set1 = new LinkedList<>();
		LinkedList<Card> set2 = new LinkedList<>();
		boolean bQueenOfSpades=false;
		for(Card theCard : cards)
			if(theCard.getCardRank()==Rank.QUEEN&&theCard.getCardSuit()==Suit.SPADES) {
				bQueenOfSpades=true;
				break;
			}
		for(Card theCard : cards) {
			if(theCard.isJoker()||(theCard.getCardRank()==Rank.QUEEN&&bQueenOfSpades))
				continue;
			if(set1.isEmpty()||theCard.getCardRank().getValue()==set1.getFirst().getCardRank().getValue())
				set1.add(theCard);
			else
				set2.add(theCard);
		}
		if(set1.isEmpty())
			throw new UnsupportedOperationException("set1 jest pusty!");
		if(set2.isEmpty()) {
			patterns.add(new WinningPattern(set1, PatternAction.PA_DEFAULT, null, null));
			return patterns;
		}
		patternsOfSets(patterns, set1, set2, null);
		patternsOfSets(patterns, set2, set1, null);
		return patterns;
	}
	
	private static void patternsOfSets(LinkedList<WinningPattern> patterns, LinkedList<Card> playSet, LinkedList<Card> paramSet, LinkedList<Card> otherSet) {
		Rank playSetRank;
		Rank paramSetRank;
		playSetRank = playSet.getFirst().getCardRank();
		paramSetRank = paramSet.getFirst().getCardRank();
		if(playSetRank==Rank.KING) {
			Card kingOfSpades=null;
			for(Card theCard: playSet)
				if(theCard.getCardSuit()==Suit.SPADES) {
					kingOfSpades=theCard;
					break;
				}
			if(kingOfSpades!=null) {
				boolean paramSpades = false;
				for(Card theCard:paramSet)
					if(theCard.getCardSuit()==Suit.SPADES) {
						paramSpades=true;
						break;
					}
				if(paramSpades)
					patterns.add(new WinningPattern(playSet, PatternAction.PA_KINGSPADES, paramSet, otherSet));
			}
		}
		else if(playSetRank==Rank.JACK) {
			if(paramSet.getFirst().bIsDemandable()||paramSet.getFirst().getCardRank()==Rank.KING)
				patterns.add(new WinningPattern(playSet, PatternAction.PA_DEMAND, paramSet, otherSet));
		}
		else if(playSetRank==Rank.ACE) {
			patterns.add(new WinningPattern(playSet, PatternAction.PA_COLORCH, paramSet, otherSet));
		}
	}
	
	public static LinkedList<WinningPattern> createOfThree(LinkedList<Card> cards) {
		LinkedList<WinningPattern> patterns = new LinkedList<>();
		LinkedList<Card> set1 = new LinkedList<>();
		LinkedList<Card> set2 = new LinkedList<>();
		LinkedList<Card> set3 = new LinkedList<>();
		boolean bQueenOfSpades=false;
		for(Card theCard : cards)
			if(theCard.getCardRank()==Rank.QUEEN&&theCard.getCardSuit()==Suit.SPADES) {
				bQueenOfSpades=true;
				break;
			}
		for(Card theCard : cards) {
			if(theCard.isJoker()||(theCard.getCardRank()==Rank.QUEEN&&bQueenOfSpades))
				continue;
			if(set1.isEmpty()||theCard.getCardRank().getValue()==set1.getFirst().getCardRank().getValue())
				set1.add(theCard);
			else if(set2.isEmpty()||theCard.getCardRank().getValue()==set2.getFirst().getCardRank().getValue())
				set2.add(theCard);
			else
				set3.add(theCard);
		}
		if(set1.isEmpty())
			throw new UnsupportedOperationException("set1 jest pusty!");
		if(set2.isEmpty())
			throw new UnsupportedOperationException("set2 jest pusty!");
		if(set3.isEmpty()) {
			patternsOfSets(patterns, set1, set2, null);
			patternsOfSets(patterns, set2, set1, null);
			return patterns;
		}
		patternsOfSets(patterns, set1, set2, set3);
		patternsOfSets(patterns, set1, set3, set2);
		patternsOfSets(patterns, set2, set1, set3);
		patternsOfSets(patterns, set2, set3, set1);
		patternsOfSets(patterns, set3, set1, set2);
		patternsOfSets(patterns, set3, set2, set1);
		return patterns;
	}
}
